package scala.com.shujia.jichu

/**
 * scala中的函数式编程
 *
 * 面向对象编程：将对象当作参数一样传来传去
 * 1、对象可以当作方法参数传递
 * 2、对象也可以当作方法的返回值返回
 * 当看到类，抽象类，接口的时候，今后无论是参数类型还是返回值类型，都需要提供对应的实现类对象
 *
 * 面向函数式编程：将函数当作参数一样传来传去
 * 1、函数A当作函数B的参数进行传递
 * 2、函数A当作函数B的返回值返回
 *
 * 在scala中，将函数也当作一个对象，对象就有类型
 * 函数在scala也有类型的说法
 * 参数类型=>返回值类型
 *
 */
object Demo10Fun {
  def main(args: Array[String]): Unit = {

    //是一个参数为字符串类型，返回值是整数类型的函数
    //    def fun1(s: String): Int = {
    //      s.toInt + 1000
    //    }
    //
    //    val res1: Int = fun1("1000")
    //    println(res1)
    //
    //    //定义变量的方式，定义一个函数
    //    //将函数当作对象，赋值给类型是函数类型的变量，将来可以直接通过变量调用函数
    //    val fun2: String => Int = fun1
    //
    //    val res2: Int = fun2("2000")
    //    println(res2)

    /**
     * 函数A作为函数B的参数定义
     *
     * 本质上是将函数A的处理逻辑主体传给了函数B，在函数B中使用这个处理逻辑
     */
    // f: String => Int  相当于函数A
    // fun1  相当于函数B
    //定义
    //    def fun1(f: String => Int): Int = {
    //      val a1: Int = f("1000")
    //      a1 + 3000
    //    }
    //
    //    def show1(s:String): Int = {
    //      s.toInt
    //    }
    //
    //    //调用
    //    val res1: Int = fun1(show1)
    //    println(res1)
    //
    //    def show2(s: String): Int = {
    //      s.toInt+11111
    //    }
    //
    //    val res2: Int = fun1(show2)
    //    println(res2)

    //定义一个函数fun1, 函数的参数列表中，既有正常的类型参数，也有函数类型的参数
    def fun1(s: String, f: String => Int): Int = {
      val a1: Int = f(s)
      a1 + 1000
    }

    //    def show1(s: String): Int = {
    //      s.toInt
    //    }
    //
    //    def show2(s: String): Int = {
    //      s.toInt + 1111
    //    }

    //.....
    //    val res1: Int = fun1("2000", show2)
    //    println(res1)

    //使用lambda表达式改写函数作为参数传递的调用形式
    fun1("2000", (s: String) => s.toInt)
    fun1("2000", (s: String) => s.toInt+1000)

    //在scala中，数据类型可以自动类型推断
    fun1("2000", s => s.toInt+1000)
    //如果当作参数的函数的参数只在函数主体使用了一次，那么可以使用_代替
    fun1("2000", _.toInt+1000)


  }
}
